Better first-run experience: smart project setup, fuzzy folder picker, optional git#555
Merged
Conversation
…eny-list) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…n-git coverage - Replace HasPrefix /tmp check with exact clean == "/tmp" to avoid wrongly blocking /tmpl-style paths - Remove .git from projectMarkerFiles since dirIsGitRepo() already covers that signal - Add TestDetectProjectFromDir_NonGitMarker: verifies go.mod-only dir yields a non-nil project with UseWorktrees=false, and empty dir yields nil Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…N parse
- Use CombinedOutput and include trimmed output in error messages for
better failure diagnostics when claude -p inference fails.
- Add WaitDelay of 2s so I/O goroutines are torn down after context
cancels the process (handles node child processes).
- Replace single-shot JSON unmarshal with forward scan from each '{' to
last '}', so stray braces in prose no longer break parsing.
- Add stray-brace test case to TestParseInferenceJSON.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…, cache home - descend() no longer returns tea.Cmd (always was nil, discarded at call site) - m.selected clamped to len-1 after filter rather than zeroed, preserving valid cursor positions - home dir cached as FolderPickerModel.home field; collapseHome converted to method to avoid per-row os.UserHomeDir() syscall Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… suggestion Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ead field Gate maybeOfferProjectCreation on isProjectCandidate (git repo OR marker files) instead of dirIsGitRepo, closing the seam where a non-git folder with e.g. package.json/go.mod received neither the suggestion card nor the welcome fork. Remove the now-dead onboardingShown struct field (its only writer was removed earlier in this task). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Convert project-form validation early-returns from bare `m.err = ...; return m, nil` to `return m.reshowProjectFormWithError(...)` so the form is re-rendered with all user-typed values intact and an inline error, instead of losing form state. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ew views, keep permission mode Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Owner
Author
…ence - ty-qa-shoot.sh: render a ty TUI screen to PNG via VHS (correct terminal sizing; tmux capture mis-reports width and corrupts modals) - ty-qa-publish.sh: upload shots to r2-personal:qa-evidence and print the PR-ready markdown image block - README: document the up -> shoot -> publish flow
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.





Summary
Overhauls the first-time experience so
tyno longer drops every user straight into a new-task form. On launch it runs a small decision tree:package.json/go.mod, minus a deny-list of junk dirs like~,Desktop,Downloads,/tmp) → an enriched "New Project Detected" card. Name/alias/description inferred withclaude -p(reuses the user's Claude CLI auth viaCLAUDE_CONFIG_DIR— no API key needed), e.g.acme-rocket→ "Acme Rocket". Inference is async: the card appears instantly with rule-based values (basename + imported README) and enriches in place — no startup freeze.personalproject → a Welcome fork:[Set up a project]/[Just start a task].~/Projects|src|code|dev|work/*seeded, git-tagged) → the same enriched card.Design calls (confirmed with product)
git initand no nag.git worktree addsucceeds with a nested repo present.Files
internal/ui/project_detect.go— candidacy heuristic + inferred-metadata merge (never erases defaults)internal/ai/project_infer.go—claude -pinference with tolerant JSON parsing + graceful degradationinternal/ui/folderpicker.go— fuzzy folder picker (reuses existingfuzzyScore, no new deps)internal/ui/welcome.go— first-run Welcome forkinternal/ui/app.go— launch decision tree, async inference, suggestion-card upgrade, dup-path guard, resize propagationinternal/ui/settings.go— validation hardeningscripts/qa/ty-qa-firstrun.sh— scripted first-run QA scenarioTest Plan
go build ./... && go test ./internal/ui/... ./internal/ai/...green;go vet+gofmtcleanpackage.json→ card withWorktrees: false; plain folder → Welcome fork; fork → picker → pick → card; esc-back; "Just start a task" → new-task form onpersonal; non-git create leaves no.git; async card shows instantly then enrichesclaudestart🤖 Generated with Claude Code